#ifndef __MY_UTIL__
#define __MY_UTIL__

#include "Log.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <jsoncpp/json/json.h>

namespace vedio_sharing {

    // 文件操作工具类，提供文件相关的常用操作
    class FileUtil {
    private:
        std::string file_path_;  // 文件路径名称

    public:
        // 构造函数，初始化文件路径
        explicit FileUtil(const std::string& file_path) : file_path_(file_path) {}

        // 判断文件是否存在
        // 返回值：如果文件存在返回 true，否则返回 false
        bool Exists() const {
            // access 的 F_OK 专门用于检测文件是否存在，存在则返回 0
            if (access(file_path_.c_str(), F_OK) != 0) {
                ERR_LOG("File is not exists: %s\n", file_path_.c_str());
                return false;
            }
            return true;
        }

        // 获取文件大小
        // 返回值：文件的大小（字节），如果文件不存在或获取失败返回 0
        size_t Size() const {
            if (!Exists()) {
                return 0;
            }
            struct stat file_stat;
            // stat 接口用于获取文件属性，其中 st_size 就是文件大小成员
            if (stat(file_path_.c_str(), &file_stat) != 0) {
                ERR_LOG("Get file stat failed: %s\n", file_path_.c_str());
                return 0;
            }
            return file_stat.st_size;
        }

        // 读取文件数据到 body 中
        // 参数 body：用于存储文件内容的字符串引用
        bool GetContent(std::string* body) const {
            std::ifstream file_stream(file_path_, std::ios::binary);
            if (!file_stream.is_open()) {
                ERR_LOG("Open file failed: %s\n", file_path_.c_str());
                return false;
            }

            const size_t file_length = Size();
            body->resize(file_length);
            file_stream.read(&(*body)[0], file_length);

            if (!file_stream.good()) {
                ERR_LOG("Read file content failed: %s\n", file_path_.c_str());
                file_stream.close();
                return false;
            }

            file_stream.close();
            return true;
        }

        // 向文件写入数据
        // 参数 body：要写入文件的字符串内容
        bool SetContent(const std::string& body) const {
            std::ofstream file_stream(file_path_, std::ios::binary);
            if (!file_stream.is_open()) {
                ERR_LOG("Open file failed: %s\n", file_path_.c_str());
                return false;
            }

            file_stream.write(body.c_str(), body.size());
            if (!file_stream.good()) {
                ERR_LOG("Write file content failed: %s\n", file_path_.c_str());
                file_stream.close();
                return false;
            }

            file_stream.close();
            return true;
        }

        // 针对目录时创建目录
        bool CreateDirectory() const {
            if (Exists()) {
                return true;
            }
            if (mkdir(file_path_.c_str(), 0777) != 0) {
                ERR_LOG("Create directory failed: %s\n", file_path_.c_str());
                return false;
            }
            return true;
        }
    };

    // JSON 操作工具类，提供 JSON 数据的序列化和反序列化功能
    class JsonUtil {
    public:
        // 将 Json::Value 对象序列化为字符串
        // 参数 value：要序列化的 Json::Value 对象
        // 参数 body：用于存储序列化结果的字符串引用
        static bool Serialize(const Json::Value& value, std::string* body) {
            Json::StreamWriterBuilder writer_builder;
            std::unique_ptr<Json::StreamWriter> writer(writer_builder.newStreamWriter());

            std::stringstream stream;
            if (writer->write(value, &stream) != 0) {
                ERR_LOG("Serialize failed!\n");
                return false;
            }

            *body = stream.str();
            return true;
        }

        // 将字符串反序列化为 Json::Value 对象
        // 参数 body：要反序列化的字符串
        // 参数 value：用于存储反序列化结果的 Json::Value 对象引用
        static bool UnSerialize(const std::string& body, Json::Value* value) {
            Json::CharReaderBuilder reader_builder;
            std::unique_ptr<Json::CharReader> reader(reader_builder.newCharReader());

            std::string error_message;
            if (!reader->parse(body.c_str(), body.c_str() + body.size(), value, &error_message)) {
                ERR_LOG("UnSerialize failed: %s\n", error_message.c_str());
                return false;
            }
            return true;
        }
    };

}

#endif